﻿namespace Reals.Existence
{
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Text;
  using Reals.Parellel;

  /// <summary>
  /// 存在(物).
  /// </summary>
  /// <remarks>
  /// 存在是微存在聚合的体现.
  /// 存在中包含有更为基本的
  /// 存在(或者微存在).
  /// 存在的组分可能附着于相
  /// 同的微循环,也可能是不
  /// 同的微循环.
  /// </remarks>
  public interface Existent<T> : MicroExistent where T:MicroExistent
  {
    /// <summary>
    /// 判别当前存在是否具有组分.
    /// </summary>
    bool HasMicroParts { get;}
    /// <summary>
    /// 获取当前存在的所有组分列表.
    /// </summary>
    IList<T> MicroParts { get; }
    /// <summary>
    /// 判别是否存在组分。
    /// </summary>
    bool HasMicroPart(T microPart);
    /// <summary>
    /// 添加微存在
    /// </summary>
    T Add(T microPart);
    /// <summary>
    /// 移除微存在。
    /// </summary>
    T Remove(T microPart);
    /// <summary>
    /// 对当前存在应用微过程节拍。
    /// </summary>
    bool Tick();
  }

  /// <summary>
  /// 存在的实现.
  /// </summary>
  public class ExistentImpl<T> : MicroExistentImpl, Existent<T> where T: MicroExistent
  {
    #region Shortcuts
    public static Existent<T> of(params T[] microParts)
    {
      return it(MicroCyclingImpl.it(), microParts);
    }
    public static Existent<T> threading(params T[] microParts)
    {
      return it(MicroThreadImpl.it(), microParts);
    }
    public static Existent<T> branching(params T[] microParts)
    {
      return it(MicroBranchImpl.it(), microParts);
    }
    public static Existent<T> it(MicroCycling cycling, params T[] microParts)
    {
      return new ExistentImpl<T>(cycling, microParts);
    }
    #endregion
    #region Fields
    protected List<T> microParts = null;
    #endregion
    #region Proprties
    public virtual bool HasMicroParts
    {
      get
      {
        return this.microParts != null && this.microParts.Count > 0;
      }
    }
    public virtual IList<T> MicroParts
    {
      get
      {
        return (this.microParts != null) ? 
          this.microParts :
          this.microParts = new List<T>();
      }
    }
    #endregion
    #region Constructors
    public ExistentImpl()
      : this(MicroCyclingImpl.it())
    {
    }
    public ExistentImpl(MicroCycling cycling, params T[] microParts)
      : base(cycling)
    {
      if (microParts != null)
      {
        foreach (T microPart in microParts)
        {
          if (microPart != null)
          {
            this.Add(microPart);
          }
        }
      }
    }
    #endregion
    #region Methods
    public virtual T Add(T microPart)
    {
      if (!this.HasMicroPart(microPart))
      {
        this.MicroParts.Add(microPart);
        microPart.Attach(this.cycling);
      }
      return microPart;
    }
    public virtual T Remove(T microPart)
    {
      if (microPart != null)
      {
        if (this.HasMicroPart(microPart))
        {
          this.MicroParts.Remove(microPart);
          microPart.Detach();
        }
      }
      return microPart;
    }
    public virtual bool HasMicroPart(T microPart)
    {
      return microPart != null && this.HasMicroParts && this.MicroParts.Contains(microPart);
    }
    public virtual bool Tick()
    {
      bool continues = false;
      if (this.HasAttached && this.Cycling.EntryProcess!=null)
      {
        continues = this.Cycling.EntryProcess();
      }
      return continues;
    }
    #region Internals
    protected override bool OnAttachCyclingTo(MicroCycling cycling)
    {
      if (this.HasMicroParts)
      {
        foreach (T existent in this.MicroParts)
        {
          if (existent != null)
          {
            existent.Attach(cycling);
          }
        }
      }

      return base.OnAttachCyclingTo(cycling);
    }
    protected override void OnDetachCyclingFrom(MicroCycling cycling)
    {
      if (this.HasMicroParts)
      {
        foreach (T existent in this.MicroParts)
        {
          if (existent != null)
          {
            existent.Detach();
          }
        }
      }
      base.OnDetachCyclingFrom(cycling);
    }
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        if (this.HasMicroParts)
        {
          foreach (T microPart in this.MicroParts)
          {
            if (microPart != null)
            {
              microPart.Dispose();
            }
          }
          this.MicroParts.Clear();
        }
      }
      base.Dispose(disposing);
    }
    #endregion
    #endregion
  }
}
